part of '../repository.dart';

const _kAdverbTypeValue = 'adverb';

class _InbuiltAdverbDto extends Equatable implements _InbuiltWordDto {
  const _InbuiltAdverbDto._internal({
    required this.id,
    required this.title,
    required this.translation,
    required this.useCaseDtos,
    required this.progressDto,
    required this.excluded,
    required this.transcriptionDtos,
    required this.imageId,
    required this.rank,
  });

  @override
  final String id;

  @override
  final String title;

  @override
  final String translation;

  @override
  final BuiltList<_UseCaseDto> useCaseDtos;

  @override
  final _LexicalItemProgressDto? progressDto;

  @override
  final bool excluded;

  @override
  final BuiltMap<_DialectDto, String> transcriptionDtos;

  @override
  final String? imageId;

  @override
  final int rank;

  @override
  String get type => _kAdverbTypeValue;

  @override
  List<Object?> get props {
    return [
      id,
      title,
      translation,
      useCaseDtos,
      progressDto,
      excluded,
      transcriptionDtos,
      imageId,
      rank,
    ];
  }

  factory _InbuiltAdverbDto.fromJson(Map<String, dynamic> json) {
    final transcriptionsMap = json[_kInbuildLexicalItemTranscriptionsKey] as Map;

    final transcriptionDtos = transcriptionsMap.map((dialectString, transcription) {
      final dialectDto = _DialectDto.fromString(dialectString);
      return MapEntry(dialectDto, transcription as String);
    }).build();

    final useCaseMaps = List.castFrom<dynamic, Map>(json[_kLexicalItemUseCasesKey]);

    final useCaseDtos = useCaseMaps.map((useCaseMap) {
      final useCaseJson = Map.castFrom<dynamic, dynamic, String, dynamic>(useCaseMap);
      return _UseCaseDto.fromJson(useCaseJson);
    }).toBuiltList();

    _LexicalItemProgressDto? progressDto;

    final lexicalItemProgressMap = json[_kLexicalItemProgressKey];

    if (lexicalItemProgressMap != null) {
      final lexicalItemProgressJson =
          Map.castFrom<dynamic, dynamic, String, dynamic>(lexicalItemProgressMap);

      progressDto = _LexicalItemProgressDtoFactory().fromJson(lexicalItemProgressJson);
    }

    return _InbuiltAdverbDto._internal(
      id: json[_kLexicalItemIdKey],
      title: json[_kLexicalItemTitleKey],
      translation: json[_kLexicalItemTranslationKey],
      transcriptionDtos: transcriptionDtos,
      useCaseDtos: useCaseDtos,
      imageId: json[_kInbuiltLexicalItemImageIdKey],
      rank: json[_kInbuiltWordRankKey],
      progressDto: progressDto,
      excluded: json[_kLexicalItemExcludedKey],
    );
  }

  factory _InbuiltAdverbDto.fromEntity(InbuiltAdverb adverb) {
    final transcriptionDtos = adverb.transcriptions.map((dialect, transcription) {
      final dialectDto = _DialectDto.fromEntity(dialect);
      return MapEntry(dialectDto, transcription);
    });

    final useCaseDtos = adverb.useCases.map((useCase) {
      return _UseCaseDto.fromEntity(useCase);
    }).toBuiltList();

    _LexicalItemProgressDto? progressDto;

    if (adverb.progress != null) {
      progressDto = _LexicalItemProgressDtoFactory().fromEntity(adverb.progress!);
    }

    return _InbuiltAdverbDto._internal(
      id: adverb.id,
      title: adverb.title,
      translation: adverb.translation,
      transcriptionDtos: transcriptionDtos,
      useCaseDtos: useCaseDtos,
      imageId: adverb.imageId,
      rank: adverb.rank,
      progressDto: progressDto,
      excluded: adverb.excluded,
    );
  }

  @override
  Map<String, dynamic> toJson() {
    final transcriptionsJson = transcriptionDtos.map((dialectDto, transcription) {
      return MapEntry(dialectDto.toString(), transcription);
    }).toMap();

    final useCaseJsons = useCaseDtos.map((useCaseDto) {
      return useCaseDto.toJson();
    }).toList();

    final json = {
      _kLexicalItemTypeKey: type,
      _kLexicalItemIdKey: id,
      _kLexicalItemTitleKey: title,
      _kLexicalItemTranslationKey: translation,
      _kInbuildLexicalItemTranscriptionsKey: transcriptionsJson,
      _kLexicalItemUseCasesKey: useCaseJsons,
      _kInbuiltLexicalItemImageIdKey: imageId,
      _kInbuiltWordRankKey: rank,
      _kLexicalItemExcludedKey: excluded,
    };

    if (progressDto != null) {
      json[_kLexicalItemProgressKey] = progressDto!.toJson();
    }

    return json;
  }

  @override
  InbuiltAdverb toEntity() {
    final transcriptions = transcriptionDtos.map((dialectDto, transcription) {
      return MapEntry(dialectDto.toEntity(), transcription);
    });

    final useCases = useCaseDtos.map((useCaseDto) {
      return useCaseDto.toEntity();
    }).toBuiltList();

    return InbuiltAdverb(
      id: id,
      title: title,
      translation: translation,
      transcriptions: transcriptions,
      useCases: useCases,
      imageId: imageId,
      rank: rank,
      progress: progressDto?.toEntity(),
      excluded: excluded,
    );
  }
}
